#include <linux/uaccess.h>
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/cdev.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/irq.h>
#include <linux/mutex.h>
#include <linux/interrupt.h>
#include <linux/bug.h>			/* For BUG_ON.  */
#include <linux/cpu.h>
#include <linux/init.h> /* Needed for the macros */
#include <linux/kernel.h> /* Needed for pr_info() */
#include <linux/module.h> /* Needed by all modules */
#include <linux/delay.h>
#include <linux/smp.h>
#include <linux/kernel_stat.h>
#include <linux/sched.h>
#include <linux/percpu-defs.h>
#include <linux/wait.h>
#include <linux/gpio/driver.h>
#include <linux/atomic.h>
#include <linux/platform_device.h>
#include <linux/poll.h>
#include <linux/kfifo.h>
#include <linux/fb.h>

/**
 *
 *   cat /dev/urandom > /dev/fb0
 *
 * fbset -xres 50 -yres 50 -depth 8
 *
 *  * You can, for example, make a screen snapshot by:

   cp /dev/fb0 myfile


   Communication is done with 16 bits per color part (red, green, blue, transparency) to support all existing hardware

   http://www.embeddedlinux.org.cn/essentiallinuxdevicedrivers/final/ch12lev1sec2.html

   https://www.jianshu.com/p/05b4aa45d20b

   https://en.wikipedia.org/wiki/Direct_Rendering_Manager

   https://archive.fosdem.org/2020/schedule/event/fbdev/attachments/slides/3595/export/events/attachments/fbdev/slides/3595/fosdem_2020_nicolas_caramelli_linux_framebuffer.pdf




   struct fb_info

Generic information, API and low level information about a specific frame buffer device instance (slot number, board address, …).

struct par

Device dependent information that uniquely defines the video mode for this particular piece of hardware.
 *
 *
 */

struct my_device_data {
	struct cdev cdev;
};

int myfb_open(struct fb_info *info, int user) {
	dev_info(info->dev, "myfb_open\n");
	return 0;
}
int myfb_release(struct fb_info *info, int user) {
	dev_info(info->dev, "myfb_release\n");
	return 0;
}
int myfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) {
	dev_info(info->dev, "myfb_check_var\n");
	return 0;
}

/* set the video mode according to info->var */
int myfb_set_par(struct fb_info *info) {
	dev_info(info->dev, "myfb_set_par\n");
	return 0;
}

struct fb_ops myfb_ops = { .owner = THIS_MODULE, .fb_open = myfb_open,
		.fb_release = myfb_release, .fb_check_var = myfb_check_var,
		.fb_set_par = myfb_set_par,

};

int myprobe(struct platform_device *pdev) {
	struct fb_info *info;
	info = framebuffer_alloc(0, &pdev->dev);
	fb_init_device(info);

info->fix  =




	info->fbops = &myfb_ops;
	fb_alloc_cmap(&info->cmap, 16, 0);
	/* Set the information in info->var to the appropriate
	 LCD controller registers */
	myfb_set_par(info);

	/* Register with the frame buffer core */
	register_framebuffer(info);
	platform_set_drvdata(pdev,info);
	pr_info("myprobe end\n");
	return 0;
}

int myremove(struct platform_device *pdev) {
	struct fb_info *info = platform_get_drvdata(pdev);
	  /* Disable screen refresh, turn off DMA,.. */
//	  myfb_disable_controller(info);
	  /* Unregister frame buffer driver */
	  unregister_framebuffer(info);
	  /* Deallocate color map */
	  fb_dealloc_cmap(&info->cmap);
	  platform_set_drvdata(pdev, NULL);
	return 0;
}

int mysuspend(struct device *pdev, pm_message_t state) {
	pr_info("myplatformdriver mysuspend \n");
	return 0;
}

int myresume(struct device *pdev) {
	pr_info("myplatformdriver myresume \n");
	return 0;
}

struct of_device_id my_of_match_table = { .compatible =
		"my_platform_device_0921", };

struct platform_driver my_platform_driver = { .driver = { .of_match_table =
		&my_of_match_table, .name = "my-fb-driver", .owner = THIS_MODULE,
		.suspend = mysuspend, .resume = myresume, }, .probe = myprobe, .remove =
		myremove, };

module_platform_driver(my_platform_driver);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andy");
MODULE_DESCRIPTION("andy one-key driver");
MODULE_ALIAS("one-key");
